<?php
/**
 * Created by b17
 * 2/27/12 8:30 PM
 */

namespace Managers;

use Managers\Exception\NoMoneyException,
Managers\Builder\UserBuilder,
Managers\Builder\AdBuilder;

class Ad extends BaseManager
{
    const TABLE = '\Catalog\Ad';
    protected $__table = self::TABLE;

    public function createQueryBuilder()
    {
        $qb = parent::createQueryBuilder()
            ->select('a, sc, c, u')
            ->from($this->__table, 'a')
            ->join('a.subCat', 'sc')
            ->join('sc.category', 'c')
            ->leftJoin('a.user', 'u')
            ->andWhere('c.isDel = 0')
            ->andWhere('a.isDel = 0')
            ->andWhere('sc.isDel = 0');
        return $qb;
    }

    /**
     * @param array $values
     * @param $user
     * @return \Catalog\Ad
     */
    public function create(array $values, $user)
    {
        $entity = new \Catalog\Ad();
        if (empty($user)) {
            $entity->setAuthor($values['author']);
            $entity->setEmail($values['email']);
        } else {
            $userRef = $this->_em->getReference(Users::TABLE, $user['id']);
            $entity->setAuthor($user['name']);
            $entity->setEmail($user['email']);
            $entity->setUser($userRef);
        }
        $subcat = $this->_em->getReference(SubCategory::TABLE, $values['subCat']);
        $entity->setSubCat($subcat);
        $entity->setDate(new \DateTime());
        $entity->setPhone($values['phone']);
        $entity->setContent($values['content']);
        $entity->setIsDel(false);

        $this->_em->persist($entity);
        $this->flush();

        return $entity;
    }

    public function getByUser($userId)
    {
        $qb = $this->createQueryBuilder()
            ->andWhere('u.id = :user')->setParameter('user', $userId);
        $res = $qb->getQuery()->getArrayResult();

        return $res;
    }

    public function delete($id, $userId)
    {
        $entity = $this->_em->getRepository($this->__table)->findOneBy(array('id' => $id, 'user' => $userId, 'isDel' => 0));
        if ($entity) {
            $entity->setIsDel(true);
            $this->_em->persist($entity);
            $this->flush();
        }
        return $entity;
    }

    public function update(array $values)
    {
        $entity = $this->find($values['id']);
        /* @var \Catalog\Ad $entity */
        $entity->setPhone($values['phone']);
        $entity->setContent($values['content']);
        $subCat = $this->_em->getReference(SubCategory::TABLE, $values['subCat']);
        $entity->setSubCat($subCat);
        $this->_em->persist($entity);
        $this->flush();
        return $entity;
    }

    public function multiplyDeletes($entities)
    {
        foreach ($entities as $entity) {
            /* @var \Catalog\Ad $entity */
            $entity->setIsDel(true);
            $this->_em->persist($entity);
        }
        $this->flush();
    }

    /**
     * Повышает привелегию объявы на 7 дней.
     * Если привелегии уже повышены, до добавляет дополнительных 7 дней.
     * В случае недостаточности счета кидает NoMoneyException.
     *
     * @param int $itemId ID объявы.
     * @param int $userId ID пользователя.
     * @throws Exception\NoMoneyException
     * @return bool|\Catalog\Ad
     */
    public function promote($itemId, $userId)
    {
        $userBuilder = new UserBuilder();
        $user = $userBuilder->setId($userId)->getOneEntity();
        /* @var \Catalog\Users $user */
        $promoteCost = $this->_getPromoteCost();
        if ($user->getMoney() < $promoteCost) {
            throw new NoMoneyException("У вас недостаточно денег.");
        }

        $adBuilder = new AdBuilder();
        $ad = $adBuilder->setId($itemId)->getOneEntity();
        /* @var \Catalog\Ad $ad */
        $ad->setPromotedDate($this->_getNewPromoteDate($ad));

        $userPayment = new UserPayment();
        $userPayment->makePayment("Rating up for $itemId.", $user, $promoteCost);

        $this->_em->persist($ad);
        $this->flush();
        return $ad;
    }

    private function _getNewPromoteDate(\Catalog\Ad $ad)
    {
        $now = new \DateTime();
        $interval = new \DateInterval('P1W');
        if ($now > $ad->getPromotedDate()) {
            $promoteTime = $now->add($interval);
        } else {
            $currentTime = clone $ad->getPromotedDate();
            $promoteTime = $currentTime->add($interval);
        }
        return $promoteTime;
    }

    /**
     * Возвращает стоимость подъема рейтинга объявы на неделю.
     *
     * @return int
     */
    private function _getPromoteCost()
    {
        return 50;
    }
}
